#include "command.h"

static void recv_file(int netFD, char *offset, char *buf);
static void sha1(char *name, char *offset1){
    char arr[1024] = { 0 };
    sprintf(arr, "sha1sum %s", name);
    char buf[1024];
    FILE *pipe = popen(arr, "r");

    fread(buf,1, sizeof(buf), pipe);
    strncpy(offset1, buf, 40);

    pclose(pipe);
}
void command_user_puts(command_t *ct, int netFD, MYSQL *conn, client_t *cl){
    int n = 1;
    send(netFD, &n, sizeof(n), MSG_NOSIGNAL);
    printf("333333333\n");
    //1、接收客户端发来的文件哈希值，用来判断服务器是否存储了该文件
    char buf[41] = { 0 };//sha1计算hash,40位
    recv(netFD, buf, 40, MSG_WAITALL);
    char state[2048] = { 0 };
    sprintf(state, "select * from file where sha1 = '%s' and offset = '%s'", buf, buf);

        char buf1[800] = { 0 };
    if(strcmp(cl->dir_path, "/") == 0){
        sprintf(buf1, "%s%s", cl->dir_path, ct->path);
    }else{
        sprintf(buf1, "%s/%s", cl->dir_path, ct->path);
    }
    int reply;
    int num = mysql_select_file_is_exist(conn, state);
    if(num >= 1){
        //2、服务器已经存在该文件，那么直接告知客户端已经上传完毕。（急速秒传）
        reply = 1;
        send(netFD, &reply, sizeof(reply), MSG_NOSIGNAL);
        //把客户端上传的记录放在表中
        bzero(state, sizeof(state));
        sprintf(state, "insert into file (status, file_name, user_name, father_id, path, file_type, md5, sha1, offset)"
                "values(1, '%s', '%s', %d, '%s', 'f', null, '%s', '%s')", ct->path, cl->name, cl->file_id, buf1, buf, buf);
        if (mysql_query(conn, state)) {
            printf("%s\n", mysql_error(conn));
            return;
        }
    }
    if(num == 0){
        //3、服务器不存在该文件，那么需要客户端上传
        //4、客户端上传一部分就断开了，就记录该文件已经接收的数据偏移量，若传完则存放文件hash值
        //到时候再传该文件的时候再从偏移量的位置进行传送（断点续传）
        reply = -1;
        send(netFD, &reply, sizeof(reply), MSG_NOSIGNAL);

        bzero(state, sizeof(state));
        sprintf(state, "select offset from file where sha1 = '%s' and user_name = '%s'", buf, cl->name);
        char offset[128] = { 0 };
        mysql_select_get_one_str(conn, state, offset);
        send(netFD, offset, sizeof(offset), MSG_NOSIGNAL);
        //准备开始接收文件
        recv_file(netFD, offset, buf);

        bzero(state, sizeof(state));
        sprintf(state, "insert into file (status, file_name, user_name, father_id, path, file_type, md5, sha1, offset)"
                "values(1, '%s', '%s', %d, '%s', 'f', null, '%s', '%s')", ct->path, cl->name, cl->file_id, buf1, buf, offset);
        if (mysql_query(conn, state)) {
            printf("%s\n", mysql_error(conn));
            return;
        }
    }
    if(num == -1){
        //测试专用
        exit(0);
    }

}
static void recv_file(int netFD, char *offset, char *buf){

    printf("11111111\n");
    //计算偏移值
    off_t flag = atoi(offset) - atoi(offset)%4096;
    //从头开始传的
    size_t file_size;
    recv(netFD, &file_size, sizeof(size_t), MSG_WAITALL);
    char curr[1024] = { 0 };
    sprintf(curr, "../user/%s", buf);
    int fd = open(curr, O_RDWR|O_CREAT, 0600);
    ERROR_CHECK(fd, -1, "open_commandputs.c");

    if(atoi(offset) == 0){
        ftruncate(fd, file_size);
    }

    char *p = (char *)mmap(NULL, file_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, flag);
    ERROR_CHECK(p, MAP_FAILED, "mmap");

    int recv_num = recv(netFD, p, file_size, MSG_WAITALL);
    ERROR_CHECK(recv_num, -1, "recv_sommandPuts.c");
    munmap(p, file_size);

    close(fd);

    char offset1[128] = { 0 };
    sha1(curr, offset1);

    bzero(offset, strlen(offset));
    if(strcmp(offset1, buf) == 0){
        //文件已经传完
        strcpy(offset, offset1);
    }else{
        sprintf(offset, "%d", recv_num);
    }

}

